import ssl

import settings
from bot.insurance_planner_gpt.config.conf import profile_
from bot.insurance_planner_gpt.context_local_util import context_data
from websockets.exceptions import ConnectionClosed
import traceback
import asyncio
import websockets

from bot.insurance_planner_gpt.planner_seat import PlannerSeat, SeatProcessPlannerMsgChannel
from bot.insurance_planner_gpt.utils.conversation_process_util import ConversationProcessUtil
from common.log import logger
from common.message import ConversationMessage
from db.redis.redis_service import RedisMemory
from util_tool.conversation_util import ConversationUtil

redis_memory = RedisMemory()
clients = {}

certfile = './common/ssl/socket.chatlingxi.com.pem'
keyfile = './common/ssl/socket.chatlingxi.com.key'

# 创建SSL上下文
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_context.load_cert_chain(certfile=certfile, keyfile=keyfile)
planner_channel = SeatProcessPlannerMsgChannel()


class SeatWorkServer:

    def __init__(self):
        self.cu = ConversationUtil()

        # 服务重启清除全部坐席链接
        takeover_to_delete = redis_memory.keys("agent_takeover:*")
        connect_to_delete = redis_memory.keys("agent_connect:*")
        # 循环遍历并删除匹配的键
        if connect_to_delete:
            connect_to_delete.extend(takeover_to_delete)
            for key in connect_to_delete:
                redis_memory.delete(key)

    async def echo(self, websocket):
        try:
            async for message in websocket:
                context_message_all = ConversationMessage.from_json(message)
                session_id = context_message_all.session_id
                context_data.set({"session_id": session_id, "message_id": 'message_id'})
                messages = context_message_all.messages
                action = context_message_all.action
                client_id = context_message_all.client_id
                target_client_id = context_message_all.target_client_id
                if not client_id:
                    client_id = context_message_all.session_id
                planner_seat = PlannerSeat(websocket, client_id, clients)

                clients[client_id] = websocket
                asyncio.create_task(planner_channel.handle_planner_channel_data(session_id, clients))
                context = ConversationMessage.format_context(messages)
                conversation = ConversationProcessUtil.format_conversation_history(context)
                # 处理坐席事件
                await planner_seat.handle_event(action, target_client_id, client_id, conversation, messages)

        except ConnectionClosed:
            # 连接正常关闭的处理
            logger.error("连接关闭-------" + traceback.format_exc())
        finally:
            self.remove_socket(websocket)

    def remove_socket(self, websocket):
        try:
            # 当客户端断开连接时，从映射中移除用户
            clients_to_remove = []
            for client_id, client in clients.items():
                if client == websocket:
                    clients_to_remove.append(client_id)
            for client_id in clients_to_remove:
                del clients[client_id]
        except Exception:
            pass

    def start(self, port):
        if settings.ONLINE:
            start_server = websockets.serve(self.echo, "0.0.0.0", port, ssl=ssl_context)
        else:
            start_server = websockets.serve(self.echo, "0.0.0.0", port, )

        asyncio.new_event_loop().run_until_complete(start_server)
        asyncio.get_event_loop().run_forever()


if __name__ == '__main__':
    seat_work_server = SeatWorkServer()
    port = profile_['seat_work_server']['port']
    port = port
    logger.info(f"********** seat work server started on port:{port} **********")
    seat_work_server.start(port=port)
